package com.tmt.im.manager.service;

import com.tmt.data.jpa.service.beans.InvalidAccessToken;
import com.tmt.data.jpa.service.beans.UserInfoVo;
import com.tmt.data.jpa.service.beans.UserLoginVo;
import com.tmt.data.jpa.service.beans.UserLogoutVo;
import com.tmt.im.common.pojo.IMUserPoJo;
import com.tmt.im.jpa.entity.IMUser;
import com.tmt.im.manager.config.beans.MySpringSessionBackedSessionRegistry;
import com.tmt.im.manager.mapstruct.IMUserMapStruct;
import com.tmt.springboot.common.restful.ExecuteResult;
import com.tmt.springboot.common.restful.IExecuteResult;
import com.tmt.springboot.common.vo.UserRegisterVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.Session;
import org.springframework.session.security.SpringSessionBackedSessionRegistry;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.util.List;

/**
 * @Description TODO
 * @Author wuyi
 * @Date 2024/8/13 11:11
 * @Version 1.0
 **/
@Service
@Slf4j
public class NotifyService<S extends Session> {

    private final SpringSessionBackedSessionRegistry<S> sessionRegistry;

    private final FindByIndexNameSessionRepository<S> sessionRepository;

    private final IMUserService imUserService;

    private final IMUserMapStruct imUserMapStruct;

    private final IgniteService igniteService;

    public NotifyService(MySpringSessionBackedSessionRegistry<S> sessionRegistry,
                         FindByIndexNameSessionRepository<S> sessionRepository,
                         IMUserService imUserService,
                         IMUserMapStruct imUserMapStruct,
                         IgniteService igniteService) {
        this.sessionRegistry = sessionRegistry;
        this.sessionRepository = sessionRepository;
        this.imUserService = imUserService;
        this.imUserMapStruct = imUserMapStruct;
        this.igniteService = igniteService;
    }

    public IExecuteResult<Boolean> processLoginNotify(UserLoginVo vo) {
        //在这里清除ignite中缓存的登出用户信息。
        igniteService.registerLoginUser(vo.getUserId());
        return ExecuteResult.success(true);
    }

    public IExecuteResult<Boolean> processLogoutNotify(UserLogoutVo vo) {
        List<SessionInformation> list = sessionRegistry.getAllSessions(vo.getUsername(), false);
        list.forEach(x -> {
            log.info(MessageFormat.format("----注销了用户{0}相关的Session对象(ID={1})----", vo.getUsername(), x));
            sessionRegistry.removeSessionInformation(x.getSessionId());
            //立即删除Session仓库中存储的对象。
            sessionRepository.deleteById(x.getSessionId());
        });

        //在这里向ignite中写入登出的用户信息。
        igniteService.registerLogoutUser(vo.getUserId(), vo.getUsername());
        return ExecuteResult.success(true);
    }

    public IExecuteResult<Boolean> processUserRegisterNotify(UserInfoVo vo) {
        try {
            IMUser user = imUserService.registerUser(vo);
            if (user == null) {
                throw new Exception(MessageFormat.format("注册用户(ID={0})失败", vo.getId()));
            }
            //更新缓存中的用户数据
            if (igniteService.loadUserPoJoIntoCache(user.getId())) {
                return ExecuteResult.success(true);
            }
        } catch (Exception ex) {
            return ExecuteResult.failure(ex.getMessage(), false);
        }
        return ExecuteResult.failure(false);
    }

    public IExecuteResult<Boolean> processUserChangedNotify(UserInfoVo vo) {
        return imUserService.updateUser(vo);
    }

    public IExecuteResult<Boolean> processUnregisterTokenNotify(InvalidAccessToken invalidAccessToken){
        //保存已注销的令牌，以便后续用来识别已废弃的令牌。
        igniteService.registerInvalidAccessToken(invalidAccessToken);
        return ExecuteResult.success(true);
    }

}
